use std::collections::HashMap;
use std::fs;
use std::sync::OnceLock;

use serde::{Deserialize, Serialize};

use crate::index::version;
use crate::runtime::runtime::path;

#[derive(Debug, Serialize, Deserialize, Clone, Default)]
pub struct Software {
    pub name: String,
    #[serde(default)]
    pub short: String,
    #[serde(default)]
    pub long: String,
    versions: Vec<version::Version>,
}

impl Software {
    pub fn get_versions(&self) -> Vec<&str> {
        let mut versions: Vec<&str> = Vec::new();

        for item in self.versions.iter() {
            versions.push(item.version.as_str())
        }

        versions
    }

    pub fn get_version(&self, version: &str) -> Option<&version::Version> {
        for item in self.versions.iter() {
            if version == item.version {
                return Some(&item);
            }
        }

        None
    }
}


/// 索引对象
static INDEX: OnceLock<HashMap<String, Software>> = OnceLock::new();

pub fn index() -> &'static HashMap<String, Software> {
    INDEX.get_or_init(|| {
        // 预创建目录
        fs::create_dir_all(path::DEM_INDEX_PATH).expect("初始化索引目录失败");
        let mut data: HashMap<String, Software> = HashMap::new();

        let dirs = fs::read_dir(path::DEM_INDEX_PATH).expect("读取索引目录失败");
        for entry in dirs.into_iter() {
            let entry = entry.expect("读取索引信息失败");

            // 隐藏文件或目录忽略，忽略非yaml文件
            if entry.file_name().to_str().unwrap().starts_with(".") || !entry.file_name().to_str().unwrap().ends_with(".yaml") {
                continue;
            }

            let metadata = entry.metadata().expect("读取索引元数据失败");

            // 忽略目录
            if metadata.is_dir() {
                continue;
            }

            let contents = fs::read_to_string(entry.path().as_path()).expect("读取索引内容失败");
            let software: Software = serde_yaml::from_str(contents.as_str()).expect("解析索引内容失败");

            let software = software;
            data.insert(software.name.to_string(), software.clone());
        }

        data
    })
}